
/*-------------------------------------------------------------------------
 *
 * varbit.h
 *	  SQL数据类型BIT()和BIT VARYING()的函数。
 *
 * 代码最初由Adriaan Joubert贡献。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/utils/varbit.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef VARBIT_H
#define VARBIT_H

#include <limits.h>

#include "fmgr.h"

/*
 * 模仿 postgres.h 中的 struct varlena，但数据类型是 bits8。
 *
 * 注意：如果 bit_len 不是 BITS_PER_BYTE 的倍数，则 bit_dat[] 
 * 的最后一个字节的低位必不可用，必须为零。
 * （这使得 bit_cmp() 不必掩码最后一个字节。）
 * 此外，头部长度中不应计算任何多余的字节。
 */
typedef struct
{
	int32		vl_len_;		/* varlena 头部（请勿直接触摸！） */
	int32		bit_len;		/* 有效位的数量 */
	bits8		bit_dat[FLEXIBLE_ARRAY_MEMBER]; /* 位字符串，最重要的字节
												 * 在前 */
} VarBit;

/*
 * fmgr 接口宏
 *
 * BIT 和 BIT VARYING 是可吐送的 varlena 类型。	
 * 从表示方式来看，它们是相同的，因此我们只有一组宏。
 */
#define DatumGetVarBitP(X)		   ((VarBit *) PG_DETOAST_DATUM(X))
#define DatumGetVarBitPCopy(X)	   ((VarBit *) PG_DETOAST_DATUM_COPY(X))
#define VarBitPGetDatum(X)		   PointerGetDatum(X)
#define PG_GETARG_VARBIT_P(n)	   DatumGetVarBitP(PG_GETARG_DATUM(n))
#define PG_GETARG_VARBIT_P_COPY(n) DatumGetVarBitPCopy(PG_GETARG_DATUM(n))
#define PG_RETURN_VARBIT_P(x)	   return VarBitPGetDatum(x)

/* 头部开销 *除此之外* VARHDRSZ */
#define VARBITHDRSZ			sizeof(int32)
/* 此位字符串中的位数 */
#define VARBITLEN(PTR)		(((VarBit *) (PTR))->bit_len)
/* 指向包含位字符串数据的第一个字节的指针 */
#define VARBITS(PTR)		(((VarBit *) (PTR))->bit_dat)
/* 位字符串数据部分的字节数 */
#define VARBITBYTES(PTR)	(VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ)
/* 位字符串末尾的填充（以位计） */
#define VARBITPAD(PTR)		(VARBITBYTES(PTR)*BITS_PER_BYTE - VARBITLEN(PTR))
/* 存储给定长度位字符串所需的字节数 */
#define VARBITTOTALLEN(BITLEN)	(((BITLEN) + BITS_PER_BYTE-1)/BITS_PER_BYTE + \
								 VARHDRSZ + VARBITHDRSZ)
/*
 * 最大位数。几个代码位置假设不会出现溢出，
 * 计算 bitlen + X；VARBITTOTALLEN() 具有最大的 X。
 */
#define VARBITMAXLEN		(INT_MAX - BITS_PER_BYTE + 1)
/* 指向位字符串末尾之后的指针（类似于 STL 容器中的 end()） */
#define VARBITEND(PTR)		(((bits8 *) (PTR)) + VARSIZE(PTR))
/* 恰好覆盖一个字节的掩码，即 BITS_PER_BYTE 位 */
#define BITMASK 0xFF

#endif
